#include "transport.h"
#include "clock.h"
#include "free-cube/time.h"

using namespace fc;
// locators
struct Transport::Locators {
    Locators (fc::TimeT l = 0,fc::TimeT r = 0, bool is_looping = false);
    fc::TimeT left;
    fc::TimeT right;
    void set_looping(bool is_looping);
    inline const bool & is_looping(){return is_looping_;}
private:
    bool is_looping_;
};

Transport::Locators::Locators(fc::TimeT l,fc::TimeT r, bool is_looping)
    : left(l), right(r) {
    set_looping(is_looping);
}

void Transport::Locators::set_looping(bool is_looping){
    is_looping_ = (left < right) && is_looping;
}
//
Transport::Transport(int samplerate, QObject *parent) :
    QObject(parent),
    samplerate_ (samplerate),
    tempo_(120.),
    time_signature_(4, fc::k_dur_quarter),
    clock_(NULL),
    size_counter_(0),
    locators_ (new Locators ()),
    is_started_(false){}

Transport::~Transport(){
    delete locators_;
}

fc::TimeT Transport::process_frames(){
    if (! is_started_) return 0;

    frames_of_stretch_ = size_counter_;
    if ( locators_->is_looping() ) {
        if (locators_->right == clock_->time());
//            clock_->set(locators_->left);
        fc::TimeT til_locator = locators_->right - clock_->time();
        if ( frames_of_stretch_ > til_locator ) {
            frames_of_stretch_ = til_locator;
        }
    }

    if (size_counter_ < frames_of_stretch_) frames_of_stretch_ = size_counter_;
    size_counter_ -= frames_of_stretch_;
    return frames_of_stretch_;
}

QString Transport::position(){ // considering bpm is constant, no tempotrack
//    return Time::string( clock_->time(), samplerate_, time_signature_, tempo_,
//                        k_bars_and_beats, 4, 0 );
};

void Transport::set_locators(fc::TimeT l,fc::TimeT r, bool is_looping){
    locators_->left = l;
    locators_->right = r;
    locators_->set_looping(is_looping);
};

fc::TimeT Transport::ticks_of_current_stretch() {
    return (tempo_ / k_min_and_sec) * // bps
            float( k_ticks_in_beat) *
            float( frames_of_stretch_) / samplerate_ ;
};

fc::TimeT Transport::position_in_ticks(){
    return (tempo_ / k_min_and_sec) * // bps
            float( k_ticks_in_beat) *
            float(clock_->time()) / samplerate_ ;
}

void Transport::set_tempo( float bpm ){ tempo_  = bpm; }
